// Copyright  2004-2008 Backplane Ltd.
//
// This file is part of Ubiquity formsPlayer
//
// Ubiquity formsPlayer is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3 of the License, or (at your
// option) any later version.
//
// Ubiquity formsPlayer is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License
// along with Ubiquity formsPlayer If not, see <http://www.gnu.org/licenses/>.
//	
//
//   Purpose:  Definition of CHTML4Win32DocumentImplementation..
//   $Id$



#include "stdafx.h"
#include <DOM2Events.h>
#include "TempDocImpl.h"
#include "FP_ReturnCodes.h"

// Construction.
CTempDocImpl::CTempDocImpl()
{
}

// Destruction.
CTempDocImpl::~CTempDocImpl()
{
}

// This method returns the implementation.
HRESULT CTempDocImpl::GetImplementation(IDOMImplementation **ppImpl)
{
	HRESULT hr = Init();

	if(SUCCEEDED(hr)) {
		if(ppImpl)
			// Return the implementation pointer.
			hr = m_pImplementation.CopyTo(ppImpl);
		else {
			hr = FP_E_BADARG;
			SetupErrorInfo(hr, L"TempDocImpl::GetImplementation");
		}
	}

	return hr;
}

// Private initialisation method.
HRESULT CTempDocImpl::Init(void)
{
	HRESULT hr = S_OK;

	if(!m_pImplementation) {
		CComBSTR sFeatures;
		IUnknown *pUnk = 0;

		// Check for XML.
		xport::GetFirstImplementation(CComBSTR(L"xml"), CComBSTR(L"1.0"), &pUnk, &m_pImplReg.p);
		if(pUnk) {
			pUnk->Release();
			pUnk = 0;
			// Add XML to the feature string.
			sFeatures += L"xml 1.0 ";
		}

		// Check for DOM level 2 events.
		xport::GetFirstImplementation(CComBSTR(L"Events"), CComBSTR(L"2.0"), &pUnk, &m_pImplReg.p);
		if(pUnk) {
			pUnk->Release();
			pUnk = 0;
			// Add DOM level 2 events to the feature string.
			sFeatures += L"Events 2.0 Events.target 2.0 Events.listener 2.0 ";
		}

		// Check for XForms 1.0.
		xport::GetFirstImplementation(CComBSTR(L"org.w3c.xforms.dom"), CComBSTR(L"1.0"), &pUnk, &m_pImplReg.p);
		if(pUnk) {
			pUnk->Release();
			pUnk = 0;
			// Add XForms 1.0 to the feature string.
			sFeatures += L"org.w3c.xforms.dom 1.0 ";
		}

		// Check for XForms 1.1.
		xport::GetFirstImplementation(CComBSTR(L"org.w3c.xforms.dom"), CComBSTR(L"1.1"), &pUnk, &m_pImplReg.p);
		if(pUnk) {
			pUnk->Release();
			pUnk = 0;
			// Add XForms 1.1 to the feature string.
			sFeatures += L"org.w3c.xforms.dom 1.1 ";
		}

		// Check for SVG.
		xport::GetFirstImplementation(CComBSTR(L"org.w3c.svg"), CComBSTR(L"1.0"), &pUnk, &m_pImplReg.p);
		if(pUnk) {
			pUnk->Release();
			pUnk = 0;
			// Add SVG to the feature string.
			sFeatures += L"org.w3c.svg 1.0 ";
		}

		// Check for MathML.
		xport::GetFirstImplementation(CComBSTR(L"org.w3c.dom.mathml"), CComBSTR(L"1.0"), &pUnk, &m_pImplReg.p);
		if(pUnk) {
			pUnk->Release();
			pUnk = 0;
			// Add MathML to the feature string.
			sFeatures += L"org.w3c.dom.mathml 1.0 ";
		}

		// Check for Microsoft Agent.
		xport::GetFirstImplementation(CComBSTR(L"speech.ms.agent"), CComBSTR(L"2.0"), &pUnk, &m_pImplReg.p);
		if(pUnk) {
			pUnk->Release();
			pUnk = 0;
			// Add Microsoft Agent to the feature string.
			sFeatures += L"speech.ms.agent 2.0 ";
		}

		// Check for the Renderer.
		xport::GetFirstImplementation(CComBSTR(L"ui.perceivableunit.renderer"), CComBSTR(L"3.0"), &pUnk, &m_pImplReg.p);
		if(pUnk) {
			pUnk->Release();
			pUnk = 0;
			// Add the Renderer to the feature string.
			sFeatures += L"ui.perceivableunit.renderer 3.0 ";
		}

		// Check for the Renderer.
		xport::GetFirstImplementation(CComBSTR(L"fp.base64"), CComBSTR(L"1.0"), &pUnk, &m_pImplReg.p);
		if(pUnk) {
			pUnk->Release();
			pUnk = 0;
			// Add the Renderer to the feature string.
			sFeatures += L"fp.base64 1.0 ";
		}
		//Check this - this may be a naughty use of .p
		hr = xport::GetImplementation(sFeatures, &m_pImplementation, &m_pImplReg.p);
	} else
		hr = S_FALSE;

	return hr;
}

// Implements document.hasFeature()
STDMETHODIMP CDocumentImplementationHasFeature::Invoke(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pdp, VARIANT *pvResult, EXCEPINFO *pexcepinfo, UINT *puArgErr)
{
	HRESULT hr = S_FALSE;

	if(wFlags & DISPATCH_METHOD && dispidMember == 0) {
		if(m_pImpl) {
			if(pdp && pdp->rgvarg && pdp->cArgs == 2 && pdp->rgvarg[0].vt == VT_BSTR && pdp->rgvarg[1].vt == VT_BSTR && pvResult) {
				VARIANT_BOOL bHasFeature = VARIANT_FALSE;
				hr = m_pImpl->hasFeature(pdp->rgvarg[1].bstrVal, pdp->rgvarg[0].bstrVal, &bHasFeature);
				if(SUCCEEDED(hr)) {
					CComVariant vResult = bHasFeature;
					vResult.Detach(pvResult);
				}
			} else
				hr = E_INVALIDARG;
		} else
			hr = E_PENDING;
	}

	return hr;
}

HRESULT CDocumentImplementationHasFeature::CreateInstance(CDocumentImplementationHasFeature **ppHasFeature)
{
	HRESULT hr = S_OK;

	try {
		if(ppHasFeature)
			*ppHasFeature = new CDocumentImplementationHasFeature;
		else
			hr = E_INVALIDARG;
	}
	catch(...) {
		hr = E_UNEXPECTED;
	}

	return hr;
}

HRESULT CDocumentImplementationHasFeature::Initialise(IDOMImplementation *pImpl)
{
	HRESULT hr = S_OK;

	if(pImpl) {
		if(!m_pImpl) {
			pImpl->AddRef();
			m_pImpl.Attach(pImpl);
		} else
			hr = S_FALSE;
	} else
		hr = E_INVALIDARG;

	return hr;
}

CDocumentImplementationHasFeature::CDocumentImplementationHasFeature()
{
}

CDocumentImplementationHasFeature::~CDocumentImplementationHasFeature()
{
}

// Implements document.getFeature()
STDMETHODIMP CDocumentImplementationGetFeature::Invoke(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pdp, VARIANT *pvResult, EXCEPINFO *pexcepinfo, UINT *puArgErr)
{
	HRESULT hr = S_FALSE;

	if(wFlags & DISPATCH_METHOD && dispidMember == 0) {
		if(m_pImpl) {
			if(pdp && pdp->rgvarg && pdp->cArgs == 2 && pdp->rgvarg[0].vt == VT_BSTR && pdp->rgvarg[1].vt == VT_BSTR && pvResult) {
				IUnknown *pUnk = 0;
				hr = m_pImpl->getFeature(pdp->rgvarg[1].bstrVal, pdp->rgvarg[0].bstrVal, &pUnk);
				if(SUCCEEDED(hr)) {
					CComVariant vResult = pUnk;
					vResult.Detach(pvResult);
				}
				if(pUnk)
					pUnk->Release();
			} else
				hr = E_INVALIDARG;
		} else
			hr = E_PENDING;
	}

	return hr;
}

HRESULT CDocumentImplementationGetFeature::CreateInstance(CDocumentImplementationGetFeature **ppGetFeature)
{
	HRESULT hr = S_OK;

	try {
		if(ppGetFeature)
			*ppGetFeature = new CDocumentImplementationGetFeature;
		else
			hr = E_INVALIDARG;
	}
	catch(...) {
		hr = E_UNEXPECTED;
	}

	return hr;
}

HRESULT CDocumentImplementationGetFeature::Initialise(IDOMImplementation *pImpl)
{
	HRESULT hr = S_OK;

	if(pImpl) {
		if(!m_pImpl) {
			pImpl->AddRef();
			m_pImpl.Attach(pImpl);
		} else
			hr = S_FALSE;
	} else
		hr = E_INVALIDARG;

	return hr;
}

CDocumentImplementationGetFeature::CDocumentImplementationGetFeature()
{
}

CDocumentImplementationGetFeature::~CDocumentImplementationGetFeature()
{
}

// Implements document.createEvent()
STDMETHODIMP CDocumentEventCreateEvent::Invoke(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pdp, VARIANT *pvResult, EXCEPINFO *pexcepinfo, UINT *puArgErr)
{
	HRESULT hr = S_FALSE;

	if(wFlags & DISPATCH_METHOD && dispidMember == 0) {
		if(m_pDocEvent) {
			if(pdp && pdp->rgvarg && pdp->cArgs == 1 && pdp->rgvarg[0].vt == VT_BSTR && pvResult) {
				CComPtr<IDOMEvent> pEvent;
				hr = m_pDocEvent->createEvent(pdp->rgvarg[0].bstrVal, &pEvent);
				if(SUCCEEDED(hr)) {
					CComVariant vResult = pEvent;
					vResult.Detach(pvResult);
				}
			} else
				hr = E_INVALIDARG;
		} else
			hr = E_PENDING;
	}

	return hr;
}

HRESULT CDocumentEventCreateEvent::CreateInstance(CDocumentEventCreateEvent **ppCreateEvent)
{
	HRESULT hr = S_OK;

	try {
		if(ppCreateEvent)
			*ppCreateEvent = new CDocumentEventCreateEvent;
		else
			hr = E_INVALIDARG;
	}
	catch(...) {
		hr = E_UNEXPECTED;
	}

	return hr;
}

HRESULT CDocumentEventCreateEvent::Initialise(void)
{
	HRESULT hr = S_OK;

	if(!m_pDocEvent)
		hr = m_pDocEvent.CoCreateInstance(CLSID_DocumentEvent);
	else
		hr = S_FALSE;

	return hr;
}

CDocumentEventCreateEvent::CDocumentEventCreateEvent()
{
}

CDocumentEventCreateEvent::~CDocumentEventCreateEvent()
{
}
